package com.ybwei.exception.demo.exception;

import com.alibaba.fastjson.JSON;
import com.ybwei.exception.demo.constant.ApiEnum;
import com.ybwei.exception.demo.vo.base.ApiResult;
import com.ybwei.exception.demo.vo.base.ApiResultGenerator;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;

/**
 * result统一异常处理 具体controller不需要单独处理异常了
 *
 * @author weiyb
 * @ClassName: RestExceptionHandler
 * @Description:
 * @date 2017年11月16日 下午2:12:52
 */
@ControllerAdvice(annotations = RestController.class)
@Slf4j
public class RestExceptionHandler {

    /**
     * 系统异常-默认统一异常处理方法
     * 不确定的异常,在返回值显示未知异常,具体错误消息进行记录和打印
     *
     * @param e 默认Exception异常对象
     * @return
     * @author weiyb
     */
    @ExceptionHandler({Exception.class})
    @ResponseBody
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public ApiResult runtimeExceptionHandler(HttpServletRequest request,Exception e) {
        //1、获取请求路径
        String requestURI = request.getRequestURI();
        //2、打印日志
        log.error("RestExceptionHandler runtimeExceptionHandler 接口{}， error:", requestURI, e);
        return ApiResultGenerator.errorResult(ApiEnum.ApiStatusEnum.EXCEPTION.getCode(), e.getMessage());
    }

    /**
     * 业务异常
     *
     * @param e
     * @return com.ybwei.exceptiondemo.vo.base.ApiResult
     * @throws
     * @methodName: bizExceptionHandler
     * @author ybwei
     * @date 2022/3/17 13:45
     */
    @ExceptionHandler(BizException.class)
    @ResponseBody
    public ApiResult bizExceptionHandler(BizException e) {
        log.error("RestExceptionHandler bizExceptionHandler error:", e);
        return ApiResultGenerator.errorResult(e.getApiStatusEnum());
    }


    /**
     * 参数校验异常
     *
     * @param e
     * @return ResultModel
     * @throws
     * @methodName: handleBindException
     * @author ybwei
     * @date 2022/3/17 10:14
     */
    @ExceptionHandler({BindException.class, MethodArgumentNotValidException.class})
    @ResponseBody
    public ApiResult handleBindException(HttpServletRequest request, Exception e) {
        //1、获取请求路径
        String requestURI = request.getRequestURI();
        //2、打印日志
        log.error("RestExceptionHandler handleBindException 接口{}， error:", requestURI, e);
        //出现参数不正确的异常,在返回值显示提示信息,具体错误消息进行记录和打印
        //设置为参数错误
        List<FieldError> fieldErrors = null;
        if (e instanceof BindException) {
            fieldErrors = ((BindException) e).getBindingResult().getFieldErrors();
        } else if (e instanceof MethodArgumentNotValidException) {
            fieldErrors = ((MethodArgumentNotValidException) e).getBindingResult().getFieldErrors();
        } else {
            return ApiResultGenerator.errorResult(ApiEnum.ApiStatusEnum.EXCEPTION.getCode(), e.getMessage());
        }
        List<String> allError = new ArrayList<>();
        //将第一个错误信息作为响应的错误信息
        //记录其他错误信息
        for (FieldError error : fieldErrors) {
            allError.add(error.getDefaultMessage());
        }
        return ApiResultGenerator.errorResult(ApiEnum.ApiStatusEnum.PARAM_INCOMPLETE.getCode(), JSON.toJSONString(allError));
    }
}
